﻿using D3StatsClient.Commands;
using D3StatsClient.Model;
using System.Windows;
using System.Windows.Input;
using System.Collections;
using System.Collections.ObjectModel;
using System.Xml.Linq;
using System.Linq;
using System;
using System.Diagnostics;
using System.Timers;
using System.Collections.Generic;
using System.Drawing;
using DBLootTrackerPlugin.ServiceModel;
using System.ServiceModel;

namespace D3StatsClient.ViewModel
{

    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<D3TrackerItem> RecordedItems { get; set; }
        public Stopwatch sw;
        private List<int> _queuedDrops = new List<int>();
        public IStatsProvider provider;
        public ILootTrackerDataService _trackerService;
        public DuplexChannelFactory<ILootTrackerDataService> trackerServiceChanel;

        //Commands
        public ICommand StartRecordingSessionCommand { get; set; }
        public ICommand StopRecordingSessionCommand { get; set; }
        public ICommand OpenSettingsWindowCommand { get; set; }
        public ICommand OpenSessionPickerCommand { get; set; }
        public ICommand ResumeSessionCommand { get; set; }
        public ICommand NewSessionCommand { get; set; }

        public MainWindowViewModel()
        {
            //init commands
            StartRecordingSessionCommand = new StartRecordingSession();
            StopRecordingSessionCommand = new StopRecordingSession();
            OpenSettingsWindowCommand = new OpenSettingsWindow();
            OpenSessionPickerCommand = new OpenSessionPicker();
            ResumeSessionCommand = new ResumeSession();
            NewSessionCommand = new NewSession();

            this.InitViewModel();
            
        }

        public void InitViewModel()
        {
            Sounds.InitSounds();

            Stats = new SessionStats();

            RecordedItems = new ObservableCollection<D3TrackerItem>();

            //timer was here.
        }

        public void EndSession()
        {
            //Stop receiving data from the tracker service.
            this._trackerService.Unsubscribe();

            //try
            //{
            //    this.trackerServiceChanel.Close();
            //}
            //catch { this.trackerServiceChanel.Abort(); }

            Status = string.Empty;
            SetStatus(false);
            IsRecording = false;
            IsContinuedSession = true;
            IsSessionLoaded = true;
            sw.Stop();
            provider.CloseConnection(sw.Elapsed);
        }


        public string GetTimeSpanFormattedString(TimeSpan span)
        {
            string formatted = string.Format("{0}{1}{2}{3}",
                  span.Days > 0 ? string.Format("{0:0} days, ", span.Days) : string.Empty,
                  span.Hours > 0 ? string.Format("{0:0} hours, ", span.Hours) : string.Empty,
                  span.Minutes > 0 ? string.Format("{0:0} minutes, ", span.Minutes) : string.Empty,
                  span.Seconds > 0 ? string.Format("{0:0} seconds", span.Seconds) : string.Empty);

            if (formatted.EndsWith(", ")) formatted = formatted.Substring(0, formatted.Length - 2);

            return formatted;
        }

        public bool SetStatus(bool status)
        {
            if (status == true)
            {
                //seemed to enable the recording in the session
            }

            if (status == false)
            {
                //seemed to disable the recording in the session
            }

            return true;
        }

        public void ReloadLoadUIData()
        {
            var provider = ((XMLStatsProvider)this.provider).XMLData;

            this.RecordedItems.Clear();

            foreach (XElement e in provider.Descendants("item"))
            {
                D3TrackerItem item = new D3TrackerItem(e.ToString(SaveOptions.DisableFormatting));
                this.RecordedItems.Add(item);
            }

            if (provider.Element("items").Attribute("played") != null)
            {
                this.SessionTime = this.GetTimeSpanFormattedString(TimeSpan.Parse(provider.Element("items").Attribute("played").Value));
            }
            else
            {
                if (provider.Element("items").Attribute("starttime") == null || provider.Element("items").Attribute("endtime") == null)
                {
                    SessionTime = this.GetTimeSpanFormattedString(new TimeSpan(0, 0, 0, 0)); //new TimeSpan().ToString("hh\\:mm\\:ss");
                }
                else
                {
                    var startTime = DateTime.Parse(provider.Element("items").Attribute("starttime").Value);
                    var endTime = DateTime.Parse(provider.Element("items").Attribute("endtime").Value);

                    SessionTime = this.GetTimeSpanFormattedString((endTime - startTime));
                }
            }

            this.XMLData_Changed(null, null);
        }

        public void XMLData_Changed(object sender, System.Xml.Linq.XObjectChangeEventArgs e)
        {
            XContainer data = sender as XContainer;

            Dispatcher.Invoke(new Action(() =>
            {
                if (data != null)
                {
                    D3TrackerItem item = new D3TrackerItem(data.ToString(SaveOptions.DisableFormatting));

                    if (e.ObjectChange == XObjectChange.Remove)
                    {
                        this.RecordedItems.Remove(this.RecordedItems.Where(i => i.ID == item.ID).FirstOrDefault());
                    }

                    if (e.ObjectChange == XObjectChange.Add)
                    {
                        
                        this.RecordedItems.Add(item);

                        if (item.IsPickedUp == false)
                        {
                            Sounds.PlayNotificationSound(item.Quality);
                        }

                    }
                }

                //Calculate total number of items
                Stats.TotalItems = RecordedItems.Count;
                //Stats.ILevel61Number = (from l in RecordedItems where (l.ItemLevel == 61) select l).Count();
                //Stats.ILevel62Number = (from l in RecordedItems where (l.ItemLevel == 62) select l).Count();
                //Stats.ILevel63Number = (from l in RecordedItems where (l.ItemLevel == 63) select l).Count();
                Stats.Rares = (from l in RecordedItems
                               where
                                   ((l.Quality == ItemQuality.Rare4)) || ((l.Quality == ItemQuality.Rare5)) || ((l.Quality == ItemQuality.Rare6))
                               select l).Count();

                Stats.Legendaries = (from l in RecordedItems
                                     where
                                         ((l.Quality == ItemQuality.Legendary))
                                     select l).Count();

                Stats.Magic = (from l in RecordedItems
                               where
                                   ((l.Quality == ItemQuality.Magic1)) || ((l.Quality == ItemQuality.Magic2)) || ((l.Quality == ItemQuality.Magic3))
                               select l).Count();

                //Stats.Set = (from l in RecordedItems
                //             where
                //                 ((l.Quality >= ItemQuality.Legendary))
                //             select l).Count();

                //Stats.ILevel63Percentage = ((double)Stats.ILevel63Number / (double)Stats.TotalItems) * 100;

            }));
        }

        #region properties


        public string Server
        {
            get { return (string)GetValue(ServerProperty); }
            set { SetValue(ServerProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Server.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ServerProperty =
            DependencyProperty.Register("Server", typeof(string), typeof(MainWindowViewModel), new PropertyMetadata("N/A"));

        public string SessionName
        {
            get { return (string)GetValue(SessionNameProperty); }
            set { SetValue(SessionNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SessionName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SessionNameProperty =
            DependencyProperty.Register("SessionName", typeof(string), typeof(MainWindowViewModel), new PropertyMetadata(string.Empty));

        

        public Process Process
        {
            get { return (Process)GetValue(ProcessProperty); }
            set { SetValue(ProcessProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Process.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ProcessProperty =
            DependencyProperty.Register("Process", typeof(Process), typeof(MainWindowViewModel), new PropertyMetadata(null));
   

        public int GoldPerHour
        {
            get { return (int)GetValue(GoldPerHourProperty); }
            set { SetValue(GoldPerHourProperty, value); }
        }

        // Using a DependencyProperty as the backing store for GoldPerHour.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty GoldPerHourProperty =
            DependencyProperty.Register("GoldPerHour", typeof(int), typeof(MainWindowViewModel), new PropertyMetadata(0));
       

        public int InitialGoldAmount
        {
            get { return (int)GetValue(InitialGoldAmountProperty); }
            set { SetValue(InitialGoldAmountProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentGoldAmount.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InitialGoldAmountProperty =
            DependencyProperty.Register("InitialGoldAmount", typeof(int), typeof(MainWindowViewModel), new PropertyMetadata(0));
    

        public bool IsContinuedSession
        {
            get { return (bool)GetValue(IsContinuedSessionProperty); }
            set { SetValue(IsContinuedSessionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsContinuedSession.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsContinuedSessionProperty =
            DependencyProperty.Register("IsContinuedSession", typeof(bool), typeof(MainWindowViewModel), new PropertyMetadata(false));
      
       
        public bool IsSessionLoaded
        {
            get { return (bool)GetValue(IsSessionLoadedProperty); }
            set { SetValue(IsSessionLoadedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsSessionLoaded.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsSessionLoadedProperty =
            DependencyProperty.Register("IsSessionLoaded", typeof(bool), typeof(MainWindowViewModel), new PropertyMetadata(false));

        public string SessionTime
        {
            get { return (string)GetValue(SessionTimeProperty); }
            set { SetValue(SessionTimeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SessionTime.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SessionTimeProperty =
            DependencyProperty.Register("SessionTime", typeof(string), typeof(MainWindowViewModel), new PropertyMetadata("00:00:00"));


        public SessionStats Stats
        {
            get { return (SessionStats)GetValue(StatsProperty); }
            set { SetValue(StatsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Stats.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StatsProperty =
            DependencyProperty.Register("Stats", typeof(SessionStats), typeof(MainWindowViewModel), new PropertyMetadata(null));
     

        public bool IsRecording
        {
            get { return (bool)GetValue(IsRecordingProperty); }
            set { SetValue(IsRecordingProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsRecording.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsRecordingProperty =
            DependencyProperty.Register("IsRecording", typeof(bool), typeof(MainWindowViewModel), new PropertyMetadata(false));

        public string Status
        {
            get { return (string)GetValue(StatusProperty); }
            set { SetValue(StatusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Status.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StatusProperty =
            DependencyProperty.Register("Status", typeof(string), typeof(MainWindowViewModel), new PropertyMetadata(string.Empty));

        public string Action
        {
            get { return (string)GetValue(ActionProperty); }
            set { SetValue(ActionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Action.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActionProperty =
            DependencyProperty.Register("Action", typeof(string), typeof(MainWindowViewModel), new PropertyMetadata(string.Empty));

        #endregion

    }
}
